home *** CD-ROM | disk | FTP | other *** search
- TITLE 'Wolfware Sample Program', 'Resident Time Display'
-
- ;----------------------------------------------;
- ; Resident Time Display ;
- ; ;
- ; A RAM resident utility which, if active, ;
- ; constantly displays the time in the the ;
- ; upper right corner. Once the utility is ;
- ; installed, the time is activated or ;
- ; deactivated with Alt-32 (hold down the Alt ;
- ; key and type 32 on the numeric keypad, then ;
- ; release the Alt key). The program is ;
- ; initially non-activated when first ;
- ; installed. Once assembled, to install, just ;
- ; type: ;
- ; ;
- ; RTIME ;
- ; ;
- ; The time is updated about three times a ;
- ; second, in the backround of whatever program ;
- ; is presently being executed. The time ;
- ; display overwrites whatever is on the screen ;
- ; at that location. The display can only be ;
- ; activated or deactivated when the foreground ;
- ; program does keyboard I/O via interrupt 16H. ;
- ; This utility uses about 1065 bytes of ;
- ; memory. ;
- ; ;
- ; For simplicity the program assumes that ;
- ; there are 65535 ticks in an hour, though ;
- ; there are actually 65543. This means that ;
- ; the displayed time is 8 ticks fast for each ;
- ; hour past midnight. The most it is off ;
- ; occurs just before midnight, when it is ;
- ; 8 * 23 = 184 ticks, or about 10 seconds fast.;
- ; As result of this the time actually runs to ;
- ; about 24:00:10 before switching to 00:00:00. ;
- ; ;
- ; This program may not be compatible with ;
- ; other RAM resident type programs. ;
- ;----------------------------------------------;
-
- PROC FAR
- JMP INSTALL ;skip to installation routine
-
- TRUE EQU -1 ;true flag
- FALSE EQU 0 ;false flag
-
- ;----- display location, location of first character of 8 byte string
-
- ROW EQU 1 ;row, 1 to 25
- COLUMN EQU 73 ;column, 1 to 80
-
- ;----- execution parameters
-
- KEY EQU 0020H ;int 16H key code to activate, Alt-32
- ATTRIBUTE EQU 70H ;display attribute, reverse video
- COUNT_SET EQU 6 ;wait count, updated 18.2/COUNT_SET = 3/sec
-
- ;----- BIOS data, at segment 0
-
- EQUIP_FLAG EQU WORD [0410H] ;equipment word
- SCREEN_COL EQU WORD [044AH] ;CRT columns
-
- ;----- interrupt location, at segement 0
-
- KEYBOARD EQU [58H] ;keyboard fetch, interrupt 16
- TIMER_TICK EQU [70H] ;timer tick vector location, interrupt 1C
-
- ;----- clock information
-
- TIMER_LOW EQU WORD [046CH] ;low word of timer, at segment 0
- TIMER_HIGH EQU WORD [046EH] ;high word of timer, at segment 0
-
- COUNTS_SEC EQU 18 ;counts in second
- COUNTS_MIN EQU 1092 ;counts in minute
- COUNTS_HOR EQU 0FFFFH ;counts in hour
-
- ;----- local stack size, stack has to handle local routines and overhead
-
- STACK EQU 20H + 80H ;size
-
- ;----------------------------------------------;
- ; INT16 ;
- ; Alternate interrupt 16H (keyboard I/O) to ;
- ; handle normal function calls while ;
- ; intercepting display activation/deactivation ;
- ; commands. Check for command only if read key ;
- ; or get keyboard status (functions 0 and 1). ;
- ;----------------------------------------------;
-
- INT16 PROC FAR
- STI ;interrupts on
- PUSHF ;save entry flags
-
- ;----- read next key
-
- OR AH,AH ;check if read key
- JNZ NONKEY ;jump if not
-
- I16GET SEG CS ;code segment
- CALL OLD_INT16 ;keyboard interrupt
- CMP AX,KEY ;check scan code
- JE SUBKEY ;jump if activate key
- IRET
-
- ;----- activation key on read
-
- SUBKEY CALL TOGGLE_ACT ;toggle present setting
- SUB SP,2 ;simulate flags for interrupt call
- SUB AH,AH ;read next key function
- JMPS I16GET ;try again
-
- ;----- keyboard status
-
- NONKEY CMP AH,1 ;check if keyboard status
- JNE NONSTAT ;jump if not
- POPF ;restore entry flags
-
- PUSHF ;flags for interrupt call
- SEG CS ;code segment
- CALL OLD_INT16 ;keyboard interrupt
- PUSHF
- JNZ I16CHKSK ;jump if key in buffer
-
- POPF
- RET 2
-
- I16CHKSK CMP AX,KEY ;check scan code
- JE I16FACT ;jump if activate key
-
- POPF
- RET 2
-
- ;----- activation key on status
-
- I16FACT SUB AH,AH ;get key function
- SUB SP,2 ;simulate flags for interrupt call
- SEG CS ;code segment
- CALL OLD_INT16 ;keyboard interrupt, get key
-
- CALL TOGGLE_ACT ;toggle present setting
-
- MOV AH,1 ;status function
- JMPS NONKEY ;try again, flags still on stack
-
- ;----- keyboard shift status or unknown function
-
- NONSTAT SEG CS ;code segment
- CALL OLD_INT16 ;keyboard interrupt, (flags on stack)
- IRET
- ENDP ;INT16
-
- ;----------------------------------------------;
- ; TOGGLE_ACT ;
- ; Toggle active setting and reset screen info. ;
- ; Clears time display (sets to dashes). ;
- ;----------------------------------------------;
-
- TOGGLE_ACT PROC NEAR
- SEG CS
- CMP ACTIVATED,TRUE ;check if on
- JE ACTOFF ;jump if so, turn off
-
- ;----- activate
-
- SEG CS
- MOV ACTIVATED,TRUE ;activate
- SEG CS
- MOV COUNTER,COUNT_SET ;reset counter
- JMPS SCREENRES
-
- ;----- deactivate
-
- ACTOFF SEG CS
- MOV ACTIVATED,FALSE ;activate off
-
- ;----- reset screen information and clear display
-
- ;----- switch to local stack
-
- SCREENRES SEG CS
- MOV STACK_SEG,SS ;save stack segment
-
- SEG CS
- MOV TEMP,CS
- SEG CS
- MOV SS,TEMP ;new stack segment
-
- SEG CS
- MOV STACK_OFF,SP ;save stack pointer
-
- SEG CS
- MOV SP,LOCAL_STK ;new stack
-
- ;----- save all registers
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSH SI
- PUSH DS
- PUSH ES
-
- CLD ;forward direction
-
- ;----- set screen information
-
- SUB AX,AX
- MOV DS,AX ;segement 0
-
- MOV BX,SCREEN_COL ;screen columns
- MOV AX,0B800H ;graphics segment
-
- MOV DX,EQUIP_FLAG ;get equipment flag
- AND DX,30H ;mask CRT bits
- CMP DX,30H ;check if BW card
- JNE NOTBW ;jump if not
-
- MOV AX,0B000H ;BW segement
-
- NOTBW MOV DX,CS
- MOV DS,DX
- MOV ES,DX ;set data segment registers
-
- MOV SCREEN_SEG,AX ;save segment
-
- ;----- calculate screen offset
-
- MOV AX,BX
- SUB DX,DX
- MUL AX,TIME_ROW ;row offset
- ADD AX,TIME_COL ;add for columns
- SHL AX ;times two, account for attribute bytes
- MOV SCREEN_OFF,AX ;save
-
- ;----- clear time display (set numbers to dashes)
-
- MOV AX,2D2DH ;dashes to clear time and date
-
- CLI ;interrupts off while display
- MOV DI,OFFSET TDISPLAY ;dislay line
- STOSW ;hours
- INC DI
- STOSW ;minutes
- INC DI
- STOSW ;seconds
-
- CALL DISPLAY ;display new string
- STI ;interrupts back on
-
- ;----- restore registers
-
- POP ES
- POP DS
- POP SI
- POP DI
- POP DX
- POP CX
- POP BX
- POP AX
-
- ;----- restore stack
-
- SEG CS
- MOV SP,STACK_OFF ;stack pointer
-
- SEG CS
- MOV SS,STACK_SEG ;stack segment
- RET
- ENDP ;TOGGLE_ACT
-
- ;----------------------------------------------;
- ; INT1C ;
- ; Alternate interrupt 1CH (timer tick). ;
- ; Executed every timer tick (about 18.2 times ;
- ; a second). ;
- ; ;
- ; One out of COUNT_SET cycles the time is ;
- ; displayed to its predetermined location, so ;
- ; the time is actually updated 18.2/COUNT_SET ;
- ; times per second. ;
- ; ;
- ; Each interrupt calls the original timer tick ;
- ; interrupt for the benefit of any other ;
- ; routines that were using it for their own ;
- ; execution. ;
- ;----------------------------------------------;
-
- INT1C PROC NEAR
- CLI ;interrupts off
-
- ;----- check if activated
-
- SEG CS
- CMP ACTIVATED,TRUE ;check if activated
- JE REDISCHK ;jump if so
-
- EXIT PUSHF ;flags for interrupt call
- SEG CS
- CALL OLD_INT1C ;call original interrupt
- IRET
-
- REDISCHK SEG CS
- DEC COUNTER ;decrement counter
- JNZ EXIT ;jump if not zero
-
- ;----- redisplay time
-
- ;----- switch to internal stack
-
- SEG CS
- MOV ACTIVATED,FALSE ;deactivate
-
- SEG CS
- MOV STACK_SEG,SS ;save stack segment
-
- SEG CS
- MOV TEMP,CS
- SEG CS
- MOV SS,TEMP ;new stack segment
-
- SEG CS
- MOV STACK_OFF,SP ;save stack pointer
-
- SEG CS
- MOV SP,LOCAL_STK ;new stack
-
- ;----- save all registers
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSH SI
- PUSH DS
- PUSH ES
-
- CLD ;forward direction
-
- ;----- get time
-
- SUB AX,AX
- MOV DS,AX ;segment 0
-
- MOV DX,[TIMER_HIGH] ;timer high
- MOV AX,[TIMER_LOW] ;timer low
-
- ;----- set time
-
- MOV BX,CS
- MOV DS,BX
- MOV ES,BX ;set segment registers
-
- MOV COUNTER,COUNT_SET ;reset counter
-
- MOV DI,OFFSET TDISPLAY ;start of time display string
-
- MOV BX,COUNTS_HOR ;counts/hour
- DIV AX,BX ;divide
- CALL NUMBER_CON ;convert to ASCII and store
- INC DI ;skip colon
-
- MOV AX,DX ;remainder is new dividend
- SUB DX,DX
- MOV BX,COUNTS_MIN ;counts/minute
- DIV AX,BX ;divide
- CALL NUMBER_CON ;convert to ASCII and store
- INC DI ;skip colon
-
- MOV AX,DX ;remainder is new dividend
- SUB DX,DX
- MOV BX,COUNTS_SEC ;counts/second
- DIV AX,BX ;divide
- CALL NUMBER_CON ;convert to ASCII and store
-
- CALL DISPLAY ;display string to screen
-
- ;----- restore registers
-
- POP ES
- POP DS
- POP SI
- POP DI
- POP DX
- POP CX
- POP BX
- POP AX
-
- ;----- restore stack
-
- SEG CS
- MOV SP,STACK_OFF ;restore stack pointer
-
- SEG CS
- MOV SS,STACK_SEG ;restore stack segment
-
- SEG CS
- MOV ACTIVATED,TRUE ;reactivate
- JMP EXIT ;exit routine
- ENDP ;INT1C
-
- ;----------------------------------------------;
- ; NUMBER_CON ;
- ; Convert number in AL to two digit ASCII ;
- ; string and store result to DI. Number must ;
- ; be in range 0 to 99. DI returns pointing to ;
- ; byte after new string. ;
- ;----------------------------------------------;
-
- NUMBER_CON PROC NEAR
- SHL AL
- SUB AH,AH ;AX gets relative offset
- ADD AX,OFFSET NUMBERS ;absolute offset
- MOV SI,AX
- MOVSW ;move word (two byte digits)
- RET
-
- ;----- data, 00 to 99
-
- NUMBERS LABEL BYTE
- DB '00010203040506070809'
- DB '10111213141516171819'
- DB '20212223242526272829'
- DB '30313233343536373839'
- DB '40414243444546474849'
- DB '50515253545556575859'
- DB '60616263646566676869'
- DB '70717273747576777879'
- DB '80818283848586878889'
- DB '90919293949596979899'
- ENDP ;NUMBER_CON
-
- ;----------------------------------------------;
- ; DISPLAY ;
- ; Display the time string to the screen by ;
- ; writing it directly to the screen buffer. ;
- ;----------------------------------------------;
-
- DISPLAY PROC NEAR
- MOV AH,ATTRIBUTE ;display attribute
- MOV CX,OFFSET TDISPLAY_END - OFFSET TDISPLAY ;length
- MOV DI,SCREEN_OFF ;offset into screen
- MOV SI,OFFSET TDISPLAY ;start of time string
- MOV ES,SCREEN_SEG ;segment of screen
-
- ;----- move string to screen buffer
-
- DISLOOP LODSB ;load character
- STOSW ;store character and attribute
- LOOP DISLOOP ;loop CX times
- RET
- ENDP ;DISPLAY
-
- ;----------------------------------------------;
- ; Data ;
- ;----------------------------------------------;
-
- ACTIVATED DB FALSE ;activation status, initially off
- COUNTER DB ? ;execution counter, set when activated
-
- TIME_ROW DW ROW - 1 ;display row
- TIME_COL DW COLUMN - 1 ;display column
-
- STACK_OFF DW ? ;storage for stack offset
- STACK_SEG DW ? ;storage for stack segment
- LOCAL_STK DW OFFSET END + STACK ;local stack top
-
- SCREEN_OFF DW ? ;screen offset
- SCREEN_SEG DW ? ;screen segment
-
- TEMP DW ? ;temporary storage
-
- ;----- display string
-
- TDISPLAY LABEL BYTE ;start of string
- DB '--:--:--'
- TDISPLAY_END LABEL BYTE ;end of string (to calculate length)
-
- ;----- original interrupts
-
- OLD_INT16 LABEL DWORD
- DW ? ;offset
- DW ? ;segment
-
- OLD_INT1C LABEL DWORD
- DW ? ;offset
- DW ? ;segment
-
- END LABEL BYTE ;end of code and data, start of stack space
-
- ;----------------------------------------------;
- ; INSTALL ;
- ; Install the alternate interrupts. ;
- ;----------------------------------------------;
-
- INSTALL PROC NEAR
- CLI ;disable interrupts
-
- ;----- install new interrupt vectors
-
- MOV AX,OFFSET INT16 ;keyboard offset
- MOV BX,CS ;present segement
- MOV CX,OFFSET INT1C ;timer offset
- MOV DX,CS ;present segement
-
- PUSH DS
- SUB BP,BP
- MOV DS,BP ;segment 0
-
- XCHG AX,WORD KEYBOARD
- XCHG BX,WORD KEYBOARD+2 ;install int 16
- XCHG CX,WORD TIMER_TICK
- XCHG DX,WORD TIMER_TICK+2 ;install int 1C
- POP DS
-
- ;----- save the old ones
-
- MOV WORD OLD_INT16,AX
- MOV WORD OLD_INT16+2,BX ;save int 16
- MOV WORD OLD_INT1C,CX
- MOV WORD OLD_INT1C+2,DX ;save int 1C
-
- STI ;enable interrupts
-
- ;----- display message
-
- MOV DX,OFFSET INSTALLM ;message location
- MOV AH,9 ;print string function
- INT 21H ;execute
-
- ;----- finish up
-
- MOV DX,LOCAL_STK ;end of interrupt, top of local stack
- INT 27H ;terminate but stay resident
-
- ;----- message
-
- INSTALLM DB 10
- DB '/-------------------------------------------\',13,10
- DB '| Resident time display utility installed |',13,10
- DB '|-------------------------------------------|',13,10
- DB '| press ALT-32 to activate/deactivate |',13,10
- DB '\-------------------------------------------/',13,10,'$'
- ENDP ;INSTALL
-
- ENDP
-